﻿using Clancy.Interfaces;
using System;
using System.Collections.Generic;

namespace Clancy.Bl.Surveilance
{
    internal class VideoBuffer
    {
        private readonly Queue<ISurveilanceResultFrame> m_Queue = new Queue<ISurveilanceResultFrame>();

        private DateTime m_EarliestFrameTime;
        private bool m_keepAllFrames;
        private DateTime m_LatestFrameTime;
        private TimeSpan m_PrefetchTime;

        public VideoBuffer(TimeSpan prefetchTime)
        {
            m_PrefetchTime = prefetchTime;
        }

        public TimeSpan BufferedVideoDuration
        {
            get { return m_LatestFrameTime - m_EarliestFrameTime; }
        }

        public ISurveilanceResultFrame[] CurrentFrames
        {
            get
            {
                return new List<ISurveilanceResultFrame>(m_Queue).ToArray();
            }
        }

        public void Clear()
        {
            m_EarliestFrameTime = DateTime.Now;
            m_LatestFrameTime = m_EarliestFrameTime;
            m_Queue.Clear();
        }

        public void Insert(ISurveilanceResultFrame frame)
        {
            m_Queue.Enqueue(frame);

            if (m_Queue.Count == 0)
                m_EarliestFrameTime = frame.Timestamp;

            m_LatestFrameTime = frame.Timestamp;

            if (!m_keepAllFrames)
                CleanOldFrames(frame.Timestamp);
        }

        public void KeepAllFrames()
        {
            m_keepAllFrames = true;
        }

        public void ReleaseOldFrames()
        {
            m_keepAllFrames = false;
        }

        private void CleanOldFrames(DateTime referenceTime)
        {
            DateTime oldestFrame = referenceTime - m_PrefetchTime;

            if (m_Queue.Count == 0)
                return;

            ISurveilanceResultFrame surveilanceResultFrame = m_Queue.Peek();
            if ((surveilanceResultFrame == null))
                return;

            m_EarliestFrameTime = surveilanceResultFrame.Timestamp;

            while (surveilanceResultFrame.Timestamp.CompareTo(oldestFrame) < 0)
            {
                m_Queue.Dequeue();
                if (m_Queue.Count == 0)
                    return;

                surveilanceResultFrame = m_Queue.Peek();
                m_EarliestFrameTime = surveilanceResultFrame.Timestamp;
            }
        }
    }
}